Skip to content

fix: rewrite agents to the real runtime VFS API#19

Merged
khaliqgant merged 1 commit into
mainfrom
fix/agents-vfs-api
Jun 2, 2026
Merged

fix: rewrite agents to the real runtime VFS API#19
khaliqgant merged 1 commit into
mainfrom
fix/agents-vfs-api

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Jun 2, 2026

Copy link
Copy Markdown
Member

These agents used a ctx.<provider> client API (ctx.linear.createIssue, ctx.github.comment, ctx.slack.post, …) that does not exist on WorkforceCtx — 33 TS2339 errors, and the if (!ctx.linear) throw guards would have thrown at runtime, so the agents were never functional.

Rewrote all 7 to the real @agentworkforce/runtime VFS API (writeJsonFile/readJsonFile/draftFile/encodeSegment/resolveMountRoot), using the canonical adapter VFS paths and writeback receipts — modeled on examples/{review-agent,linear-shipper,notion-essay-pr}. Control flow and the real ctx.harness/llm/files/sandbox/memory/log usage are preserved.

tsc --noEmit is clean (0 errors); no ctx.<provider> references remain.

🤖 Generated with Claude Code


Summary by cubic

Rewrote all seven agents to use the real @agentworkforce/runtime VFS API instead of non-existent ctx.<provider> calls, fixing 33 TS errors and runtime crashes. Agents now interact with GitHub, Linear, Slack, and Notion via Relayfile and are functional.

  • Bug Fixes

    • Replaced invalid ctx.github/ctx.linear/ctx.slack/ctx.notion calls with VFS helpers (writeJsonFile, readJsonFile, draftFile, encodeSegment, resolveMountRoot).
    • Handled writeback receipts for issue URLs/IDs, PR merges, and Notion page URLs; log warnings when receipts are missing.
    • Removed throwing integration guards; tsc is clean (0 errors).
  • Refactors

    • Standardized canonical VFS paths for GitHub (PR meta/comments/merge), Linear (issues/comments), Slack (channels/users), and Notion (database pages).
    • Added a vfsClient() helper to supply relayfileMountRoot.
    • Preserved existing control flow and ctx.harness/llm/files/sandbox/memory/log usage.

Written for commit 8ef61ac. Summary will update on new commits.

Review in cubic

…x.<provider>)

These agents called a ctx.github/ctx.linear/ctx.slack/ctx.notion client API that
does not exist on WorkforceCtx — 33 TS2339 errors, and the `if (!ctx.linear)`
guards would have thrown at runtime (the agents were never functional). Rewrote
all 7 to the real VFS helpers (writeJsonFile/readJsonFile/draftFile/
encodeSegment/resolveMountRoot), mirroring examples/{review-agent,linear-shipper,
notion-essay-pr}: provider reads/writes go through canonical VFS paths and
writeback receipts. Control flow + ctx.harness/llm/files/sandbox/memory/log
preserved. tsc clean (0 errors); no ctx.<provider> references remain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Seven agents (granola, hn-monitor, linear, repo-hygiene, review, spotify-releases, vendor-monitor) are refactored to route integration requests through a VFS relay mechanism. Instead of calling ctx.linear.createIssue, ctx.slack.post, or ctx.github.comment directly, agents now use writeJsonFile and readJsonFile to exchange JSON payloads with relay-mounted integration services. Guards requiring integration availability are removed, and responses are processed from returned receipts.

Changes

VFS relay migration for agent integrations

Layer / File(s) Summary
VFS relay infrastructure and imports
granola/agent.ts, hn-monitor/agent.ts, linear/agent.ts, repo-hygiene/agent.ts, review/agent.ts, spotify-releases/agent.ts, vendor-monitor/agent.ts
All agents import VFS utilities (draftFile, encodeSegment, resolveMountRoot, writeJsonFile, readJsonFile) and define a local vfsClient() helper that constructs IntegrationClientOptions with relayfileMountRoot.
Linear integration migration
granola/agent.ts, linear/agent.ts
granola removes the ctx.linear guard, writes a linear/createIssue request via VFS, and conditionally writes a linear/comment request when both prUrl and issueId are available. linear initializes a VFS client, reads issue JSON from /linear/issues/{issueId}.json, and writes PR-link comments to /linear/issues/{issueId}/comments/{draftFile('comment')}.
Slack integration migration for simple agents
hn-monitor/agent.ts, spotify-releases/agent.ts, vendor-monitor/agent.ts
hn-monitor, spotify-releases, and vendor-monitor remove ctx.slack guards and replace direct Slack API calls with writeJsonFile calls to VFS relay paths constructed using encodeSegment for channels/users and draftFile for message identifiers.
GitHub and Notion integration migration for complex agents
repo-hygiene/agent.ts, review/agent.ts
repo-hygiene uses readJsonFile for PR metadata, writeJsonFile for PR comments and Slack messages, and refactors writeNotionJournal to request Notion page creation via VFS. review simplifies the webhook guard, refactors reviewAndFix and failReviewRun to draft GitHub comments and Slack messages via VFS, and rewrites mergePr to submit merge requests via VFS with receipt-based validation.

Sequence Diagram(s)

sequenceDiagram
  participant LinearAgent
  participant VFS as VFS Relay
  participant LinearAPI as Linear API
  LinearAgent->>VFS: writeJsonFile(linear/createIssue)
  VFS->>LinearAPI: Create issue request
  LinearAPI-->>VFS: receipt {issueId, issueUrl}
  VFS-->>LinearAgent: return receipt
  LinearAgent->>VFS: writeJsonFile(linear/comment)
  VFS->>LinearAPI: Post PR-link comment
  LinearAPI-->>VFS: receipt
  VFS-->>LinearAgent: return receipt
Loading
sequenceDiagram
  participant ReviewAgent
  participant VFS as VFS Relay
  participant GithubAPI as GitHub API
  ReviewAgent->>VFS: writeJsonFile(/pulls/N/comment)
  VFS->>GithubAPI: Post PR comment
  GithubAPI-->>VFS: receipt
  VFS-->>ReviewAgent: return receipt
  ReviewAgent->>VFS: writeJsonFile(/pulls/N/merge.json)
  VFS->>GithubAPI: Merge PR (squash method)
  GithubAPI-->>VFS: receipt {merged: true}
  VFS-->>ReviewAgent: return receipt?.merged
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • AgentWorkforce/agents#2: Modifies review/agent.ts merge flow; this PR also rewrites mergePr to route through the VFS relay instead of direct ctx.github calls.
  • AgentWorkforce/agents#7: Introduced initial repo-hygiene/agent.ts logic using direct integration calls; this PR refactors the same agent to use VFS relay for GitHub/Slack/Notion operations.
  • AgentWorkforce/agents#14: Also modifies review/agent.ts harness-driven behavior; this PR refactors review comment/merge/Slack flows through VFS while preserving harness output handling.

Poem

🐰 Seven agents now dance with the VFS,
No more direct calls—they relay their request,
Linear, GitHub, Slack—all through the mount,
Drafts and receipts make the flow count,
Hop along, integration dreams come true!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: rewrite agents to the real runtime VFS API' directly and clearly summarizes the main change: replacing non-existent ctx. calls with the real @agentworkforce/runtime VFS API across all seven agents.
Description check ✅ Passed The description is detailed and directly related to the changeset, explaining the problem (33 TS errors from non-existent ctx. calls), the solution (migration to real VFS API), and the benefits (clean type-checking, functional agents).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/agents-vfs-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors several agents to migrate from direct integration clients on ctx (such as ctx.linear, ctx.slack, ctx.github, and ctx.notion) to a Virtual File System (VFS) approach using readJsonFile and writeJsonFile from @agentworkforce/runtime. Feedback on the changes highlights potential runtime crashes in linear/agent.ts and repo-hygiene/agent.ts if readJsonFile returns null or undefined, recommending the addition of guard checks to handle missing files or VFS read failures safely.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread linear/agent.ts
Comment on lines +57 to +62
const issue = await readJsonFile<LinearIssue>(
client,
'linear',
'getIssue',
`/linear/issues/${encodeSegment(issueId)}.json`
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The readJsonFile call can return null or undefined if the issue is not found or the VFS read fails. We should add a guard check to prevent a potential runtime crash when passing issue to parseRepo(issue).

  const issue = await readJsonFile<LinearIssue>(\n    client,\n    'linear',\n    'getIssue',\n    \`/linear/issues/${encodeSegment(issueId)}.json\`\n  );\n  if (!issue) {\n    ctx.log('warn', 'linear-implementer.issue-not-found', { issueId });\n    return;\n  }

Comment thread repo-hygiene/agent.ts
Comment on lines +78 to +83
const details = await readJsonFile<GithubPrMeta>(
client,
'github',
'getPr',
`/github/repos/${encodeSegment(pr.owner)}/${encodeSegment(pr.repo)}/pulls/${pr.number}/meta.json`
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The readJsonFile call can return null or undefined if the file is missing or the VFS read fails. We should add a guard check to prevent a potential runtime crash when accessing details.diff.

  const details = await readJsonFile<GithubPrMeta>(\n    client,\n    'github',\n    'getPr',\n    \`/github/repos/${encodeSegment(pr.owner)}/${encodeSegment(pr.repo)}/pulls/${pr.number}/meta.json\`\n  );\n  if (!details) {\n    ctx.log('warn', 'repo-hygiene.pr-details-not-found', { pr });\n    return;\n  }

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
linear/agent.ts (1)

57-62: 💤 Low value

Consider handling readJsonFile failures gracefully.

If the Linear issue doesn't exist or the VFS read fails, readJsonFile may throw or return unexpected data. The issue.title access on Line 75 assumes the issue was successfully fetched.

💡 Optional: wrap readJsonFile in try-catch
-  const issue = await readJsonFile<LinearIssue>(
-    client,
-    'linear',
-    'getIssue',
-    `/linear/issues/${encodeSegment(issueId)}.json`
-  );
+  let issue: LinearIssue;
+  try {
+    issue = await readJsonFile<LinearIssue>(
+      client,
+      'linear',
+      'getIssue',
+      `/linear/issues/${encodeSegment(issueId)}.json`
+    );
+  } catch (err) {
+    ctx.log?.('warn', 'linear.issue-read-failed', { issueId, error: String(err) });
+    return;
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@linear/agent.ts` around lines 57 - 62, The call to readJsonFile that sets
const issue should be made resilient: wrap the readJsonFile(...) call in a
try-catch (or handle its Promise rejection) inside the surrounding function,
catch errors from readJsonFile/encodeSegment, log or surface the error, and
ensure you validate that the returned issue is non-null and has expected fields
(e.g., issue.title) before using them; update any downstream code that assumes
issue.title (in this file/function) to handle a missing issue by returning
early, throwing a clear error, or using a safe fallback.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@linear/agent.ts`:
- Around line 57-62: The call to readJsonFile that sets const issue should be
made resilient: wrap the readJsonFile(...) call in a try-catch (or handle its
Promise rejection) inside the surrounding function, catch errors from
readJsonFile/encodeSegment, log or surface the error, and ensure you validate
that the returned issue is non-null and has expected fields (e.g., issue.title)
before using them; update any downstream code that assumes issue.title (in this
file/function) to handle a missing issue by returning early, throwing a clear
error, or using a safe fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b3bfb5b7-e744-4142-b752-546f34c4fc78

📥 Commits

Reviewing files that changed from the base of the PR and between 55e6826 and 8ef61ac.

📒 Files selected for processing (7)
  • granola/agent.ts
  • hn-monitor/agent.ts
  • linear/agent.ts
  • repo-hygiene/agent.ts
  • review/agent.ts
  • spotify-releases/agent.ts
  • vendor-monitor/agent.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="granola/agent.ts">

<violation number="1" location="granola/agent.ts:59">
P2: PR-link comment can be dropped when `createIssue` receipt arrives late because `issueId` is captured once and never refreshed.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread granola/agent.ts
// the Linear create lands. Without a receipt we can't link the issue or
// address a follow-up comment, so log and continue with the implementation.
const issueUrl = created.receipt?.url;
const issueId = created.receipt?.id ?? created.receipt?.identifier;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: PR-link comment can be dropped when createIssue receipt arrives late because issueId is captured once and never refreshed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At granola/agent.ts, line 59:

<comment>PR-link comment can be dropped when `createIssue` receipt arrives late because `issueId` is captured once and never refreshed.</comment>

<file context>
@@ -33,18 +44,44 @@ export default defineAgent({
+  // the Linear create lands. Without a receipt we can't link the issue or
+  // address a follow-up comment, so log and continue with the implementation.
+  const issueUrl = created.receipt?.url;
+  const issueId = created.receipt?.id ?? created.receipt?.identifier;
+  if (!issueUrl) {
+    ctx.log('warn', 'granola-prospect.issue.no-receipt', { draftPath: created.path });
</file context>

@khaliqgant khaliqgant merged commit daca1a3 into main Jun 2, 2026
2 checks passed
@khaliqgant khaliqgant deleted the fix/agents-vfs-api branch June 2, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant